package com.kdtech.utils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;
import java.io.Reader;
import java.io.Writer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;

/**
 * 与java i/o相关操作的辅助类
 * @author kk
 *
 */
public class IOUtils {
    /**
     * Read lines combined with ' '.
     * Will not close the input stream afterward.
     */
    public static String ReadStringContent(InputStream inputStream, String encoding) throws IOException {
    	return ReadStringContent(inputStream, encoding, false, null);
    }

    public static String ReadStringContent(File file, String charset) throws IOException {
		InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(file),charset);
		return ReadString(inputStreamReader);
	}
    /**
     * @param commentLineStarts if not null, blank lines and lines starting with the given string will be ignored
     */
    public static String ReadStringContent(InputStream inputStream, String encoding, boolean trimLine, String commentLineStarts) throws IOException {
        return ReadStringContent(inputStream, encoding, trimLine, commentLineStarts, true);
    }


    /**
     * @param commentLineStarts if not null, blank lines and lines starting with the given string will be ignored
     * @param isSkipOnEmptyLine if true, blank lines will be ignored
     */
    public static String ReadStringContent(InputStream inputStream, String encoding, boolean trimLine, String commentLineStarts, boolean isSkipOnEmptyLine) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, encoding));
        return ReadStringContent(reader, trimLine, commentLineStarts, isSkipOnEmptyLine);
    }

    /**
     * Read lines combined with ' '.
     * Will not close the reader afterward.
     */
    public static String ReadStringContent(Reader inputReader) throws IOException {
        return ReadStringContent(inputReader, false, null, true);
    }
    /**
     * @param commentLineStarts if not null, blank lines and lines starting with the given string will be ignored
     */
    public static String ReadStringContent(Reader inputReader, boolean trimLine, String commentLineStarts, boolean isSkipOnEmptyLine) throws IOException {
        StringBuilder buffer = null;
        BufferedReader reader = new BufferedReader(inputReader);
        while (true) {
            String line = reader.readLine();
            if (line == null)
                break;
            String trimmedLine = line.trim();
            if (trimLine)
                line = trimmedLine;
            if ("".equals(line) && isSkipOnEmptyLine)
                continue;
            if (commentLineStarts != null && trimmedLine.startsWith(commentLineStarts))
                continue;
            if (buffer == null)
                buffer = new StringBuilder();
            else
                buffer.append(' ');
            buffer.append(line);
        }
        return buffer != null ? buffer.toString() : "";
    }
    public static void WriteStringContent(File file, String data, String encoding) throws IOException {
    	FileOutputStream fos = new FileOutputStream(file);
    	Writer writer = new OutputStreamWriter(fos, encoding);
        writer.write(data);
        writer.flush();
        writer.close();
    }

    public static void WriteStringContent(String file, String data, String encoding) throws IOException {
    	FileOutputStream fos = new FileOutputStream(file);
    	Writer writer = new OutputStreamWriter(fos, encoding);
        writer.write(data);
        writer.flush();
        writer.close();
    }
    /**
     * Will not close the output stream afterward.
     */
    public static void WriteStringContent(OutputStream outputStream, String data, String encoding) throws IOException {
        Writer writer = new OutputStreamWriter(outputStream, encoding);
        writer.write(data);
        writer.flush();
    }
    /**
     * Will not close the input stream afterward.
     */
    public static byte[] ReadBytes(InputStream inputStream) throws IOException {
        ByteArrayOutputStream bufferOS = new ByteArrayOutputStream();
        CopyInputStreamToOutputStream(inputStream, bufferOS);
        bufferOS.close();
        return bufferOS.toByteArray();
    }
    /**
     * Will not close the output stream afterward.
     */
    public static void WriteBytes(OutputStream outputStream, byte[] bytes) throws IOException {
        ByteArrayInputStream is = new ByteArrayInputStream(bytes);
        CopyInputStreamToOutputStream(is, outputStream);
    }
    /**
     * Will not close the input stream afterward.
     */
    public static char[] ReadChars(Reader reader) throws IOException {
        CharArrayWriter bufferWriter = new CharArrayWriter();
        CopyReaderToWriter(reader, bufferWriter);
        bufferWriter.close();
        return bufferWriter.toCharArray();
    }

    public static String ReadString(Reader reader) throws IOException {
        CharArrayWriter bufferWriter = new CharArrayWriter();
        CopyReaderToWriter(reader, bufferWriter);
        bufferWriter.close();
        return bufferWriter.toString();
    }

    public static String ReadString(String file) throws IOException {
        return ReadString(new File(file));
    }

    public static String ReadString(File file) throws IOException {
    	FileReader reader = new FileReader(file);
    	String readString = ReadString(reader);
    	reader.close();
    	return readString;
    }
    /**
     * Will not close the reader afterward.
     */
    public static ArrayList ReadLineAsList(Reader reader) throws IOException {
    	return ReadLineAsList(reader, false, null);
    }

    public static ArrayList ReadLineAsList(File file,String encoding) throws IOException {
    	InputStreamReader reader = new InputStreamReader(new FileInputStream(file),encoding);
        ArrayList readLineAsList = ReadLineAsList(reader);
        reader.close();
        return readLineAsList;
    }
    /**
     * Will not close the reader afterward.
     * @param commentLineStarts if not null, blank lines and lines starting with the given string will be ignored
     */
    public static ArrayList<String> ReadLineAsList(Reader reader, boolean trimLine, String commentLineStarts) throws IOException {
        BufferedReader bufferedReader;
        if (reader instanceof BufferedReader)
            bufferedReader = (BufferedReader) reader;
        else
            bufferedReader = new BufferedReader(reader);
        ArrayList<String> lines = new ArrayList<String>();
        while (true) {
            String line = bufferedReader.readLine();
            if (line == null)
                break;
            String trimmedLine = line.trim();
            if (trimLine)
                line = trimmedLine;
            if (commentLineStarts != null) {
                if ("".equals(trimmedLine) || trimmedLine.startsWith(commentLineStarts))
                    continue;
            }
            if (line != null)
                lines.add(line);
        }
        return lines;
    }
    /**
     * Will not close the IO streams afterward.
     */
    public static void CopyInputStreamToOutputStream(InputStream is, OutputStream os) throws IOException {
		byte buf[] = new byte[4096];
		int bytesRead = is.read(buf);
		while (bytesRead >= 0) {
			os.write(buf, 0, bytesRead);
			bytesRead = is.read(buf);
		}
	}

    public static void CopyFile(File is, File os) throws IOException {
			FileInputStream fis = new FileInputStream(is);
			FileOutputStream fos = new FileOutputStream(os);
			CopyInputStreamToOutputStream(fis,fos);
			fis.close();
			fos.close();
	}
    /**
     * Will not close the read and writer aferward.
     */
    public static void CopyReaderToWriter(Reader reader, Writer writer) throws IOException {
        char[] buffer = new char[10240];
        while (true) {
            int c = reader.read(buffer);
            if (c == -1)
                break;
            if (c > 0)
                writer.write(buffer, 0, c);
        }
    }

	/**
	 * append String to file.
	 *
	 * @param filename
	 * @param str
	 * @throws IOException
	 */
	public static void appendStringToFile(String filename, String str)
	 throws IOException {
		BufferedWriter writer = new BufferedWriter (
		new FileWriter(filename, true));
		writer.write(str);
		writer.flush();
		writer.close();
	}

	public static void appendStringToFile(File filename, String str) throws IOException {
		BufferedWriter writer = new BufferedWriter (new FileWriter(filename, true));
		writer.write(str);
		writer.flush();
		writer.close();
	}

	/**
	 * Load contents from a file in the classpath
	 *
	 * @param classLoader - class loader for loading the resource
	 * @param resourceClassPath - classpath of the resource
	 * @return content from the resource
	 * @throws IOException - when there is an exception while loading the resource
	 */
	public static String getContentFromStream(ClassLoader classLoader, String resourceClassPath) throws IOException {
		StringBuilder content = new StringBuilder();
		InputStream is = null;
		BufferedReader br = null;
		try {
			is = classLoader.getResourceAsStream(resourceClassPath);
			br = new BufferedReader(new InputStreamReader(is));
			String line = null;
			while ((line = br.readLine()) != null) {
				content.append(line + " ");
			}
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					// doesn't matter
				}
			}
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					// doesn't matter
				}
			}
		}
		return content.toString();
	}
	public static byte[] longToByte(long v) {
		 byte[] b = new byte[8];
		 b[0] = (byte) ( (v >>> 56) & 0xFF);
		 b[1] = (byte) ( (v >>> 48) & 0xFF);
		 b[2] = (byte) ( (v >>> 40) & 0xFF);
		 b[3] = (byte) ( (v >>> 32) & 0xFF);
		 b[4] = (byte) ( (v >>> 24) & 0xFF);
		 b[5] = (byte) ( (v >>> 16) & 0xFF);
		 b[6] = (byte) ( (v >>> 8) & 0xFF);
		 b[7] = (byte) ( (v >>> 0) & 0xFF);
        return b;
    }

	//byte数组转成long
    public static long byteToLong(byte[] b) {
        long s = 0;
        long s0 = b[0] & 0xff;// 最低位
        long s1 = b[1] & 0xff;
        long s2 = b[2] & 0xff;
        long s3 = b[3] & 0xff;
        long s4 = b[4] & 0xff;// 最低位
        long s5 = b[5] & 0xff;
        long s6 = b[6] & 0xff;
        long s7 = b[7] & 0xff;

        // s0不变
        s1 <<= 8*7;
        s2 <<= 8*6;
        s3 <<= 8*5;
        s4 <<= 8 *3;
        s5 <<= 8 *2;
        s6 <<= 8 * 1;
        s7 <<= 8 * 0;
        s = s0 | s1 | s2 | s3 | s4 | s5 | s6 | s7;
        return s;
    }

    /**
     * 注释：int到字节数组的转换！
     *
     * @param number
     * @return
     */
    public static byte[] intToByte(int number) {
        int temp = number;
        byte[] b = new byte[4];
        for (int i = 0; i < b.length; i++) {
            b[i] = new Integer(temp & 0xff).byteValue();//
            //将最低位保存在最低位
            temp = temp >> 8; // 向右移8位
        }
        return b;
    }

    /**
     * 注释：字节数组到int的转换！
     *
     * @param b
     * @return
     */
    public static int byteToInt(byte[] b) {
        int s = 0;
        int s0 = b[0] & 0xff;// 最低位
        int s1 = b[1] & 0xff;
        int s2 = b[2] & 0xff;
        int s3 = b[3] & 0xff;
        s3 <<= 24;
        s2 <<= 16;
        s1 <<= 8;
        s = s0 | s1 | s2 | s3;
        return s;
    }

    /**
     * 注释：short到字节数组的转换！
     *
     * @param s
     * @return
     */
    public static byte[] shortToByte(short number) {
        int temp = number;
        byte[] b = new byte[2];
        for (int i = 0; i < b.length; i++) {
            b[i] = new Integer(temp & 0xff).byteValue();//
            //将最低位保存在最低位
            temp = temp >> 8; // 向右移8位
        }
        return b;
    }

    /**
     * 注释：字节数组到short的转换！
     *
     * @param b
     * @return
     */
    public static short byteToShort(byte[] b) {
        short s = 0;
        short s0 = (short) (b[0] & 0xff);// 最低位
        short s1 = (short) (b[1] & 0xff);
        s1 <<= 8;
        s = (short) (s0 | s1);
        return s;
    }

	/**
	 * 返回文件读写管道
	 * @param file
	 * @param mutable	是否可写
	 * @return
	 * @throws FileNotFoundException
	 */
    @SuppressWarnings("resource")
	public static FileChannel openChannel(File file, boolean mutable) throws FileNotFoundException {
		if (mutable){
			return new RandomAccessFile(file, "rw").getChannel();
		}
		return new FileInputStream(file).getChannel();
	}

	public static String getWorkPath() {
		String pkgname = IOUtils.class.getPackage().getName();
		pkgname = pkgname.replace('.', '/');
		String path = IOUtils.class.getResource("").getPath();
		path = path.replace(pkgname, "");
		path = path.replace("\\\\", "/");
		path = path.replace("//", "/");
		return path;
	}

	public static void createFile(File file) throws IOException {
		if (!file.exists()){
			if (!file.getParentFile().exists()){
				file.getParentFile().mkdirs();
			}
			file.createNewFile();
		}
	}



}
